﻿using ArtMath.Attribute;
using ArtMath.Component.Line;
using ArtMath.Component.Point;
using ArtMath.Converter;
using ArtMath.Core.Data;
using ArtMath.Core.Helper;
using ArtMath.Helper;
using ArtMath.Resource;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using ArtMath.CommonType;

namespace ArtMath.Component.Polygon
{
    /// <summary>
    /// 三角形基类
    /// </summary>
    [Serializable]
    public abstract class TriangleBase : PolygonBase
    {
        PropertyDisplayer nxDisplayer, wxDisplayer, cxDisplayer;
        public TriangleBase(SketchPad pad, string name, ToolTypeName toolType, bool addToList = true) : base(pad, name, toolType, addToList)
        {
            for (int i = 0; i < 3; i++)
            {
                Lines.Add(null);
            }
            InPoints = new PointBase[3];
            //pxs = new PointD[3];
            //Ppxs = new PointD[3];
            InCenterDisplayer = new PropertyDisplayer(this, "InCenter") { OffSet = AnchorOffset };
            CircumCenterDisplayer = new PropertyDisplayer(this, "CircumCenter") { OffSet = AnchorOffset };
            OrthoCenterDisplayer = new PropertyDisplayer(this, "OrthoCenter") { OffSet = AnchorOffset };
        }
        [Browsable(false)]
        public override List<LineSegmentBase> Lines
        {
            get
            {
                return base.Lines;
            }
        }
        /// <summary>
        /// 内心
        /// </summary>
        [MultilingualCategory("Parameter"), MultilingualDisplayName("InCenter"), TypeConverter(typeof(IntelliPointConverter))]
        public PointD InCenter { get; private set; }
        [Browsable(false)]
        public PointD NewInCenter
        {
            get { return Utility.GetInCenter(InPoints[0].NewXY, InPoints[1].NewXY, InPoints[2].NewXY); }
        }
        [Browsable(false)]
        public PointD PInCenter { get; private set; }
        [Browsable(false)]
        public PointD NewPInCenter
        {
            get { return Pad.XYToPxy(NewInCenter); }
        }
        /// <summary>
        /// 外心
        /// </summary>
        [MultilingualCategory("Parameter"), MultilingualDisplayName("CircumCenter"), TypeConverter(typeof(IntelliPointConverter))]
        public PointD CircumCenter { get; private set; }
        [Browsable(false)]
        public PointD NewCircumCenter
        {
            get { return Utility.GetCircumCenter(InPoints[0].NewXY, InPoints[1].NewXY, InPoints[2].NewXY); }
        }
        [Browsable(false)]
        public PointD PCircumCenter { get; private set; }
        [Browsable(false)]
        public PointD NewPCircumCenter
        {
            get { return Pad.XYToPxy(NewCircumCenter); }
        }
        /// <summary>
        /// 垂心
        /// </summary>
        [MultilingualCategory("Parameter"), MultilingualDisplayName("OrthoCenter"), TypeConverter(typeof(IntelliPointConverter))]
        public PointD OrthoCenter { get; private set; }
        [Browsable(false)]
        public PointD NewOrthoCenter
        {
            get { return Utility.GetOrthoCenter(InPoints[0].NewXY, InPoints[1].NewXY, InPoints[2].NewXY); }
        }
        [Browsable(false)]
        public PointD POrthoCenter { get; private set; }
        [Browsable(false)]
        public PointD NewPOrthoCenter
        {
            get { return Pad.XYToPxy(NewOrthoCenter); }
        }
        ///// <summary>
        ///// 旁心
        ///// </summary>
        //[Browsable(false)]
        //public PointD[] EsCenters
        //{
        //    get { return pxs; }
        //}
        //[Browsable(false)]
        //public PointD[] PEsCenters
        //{
        //    get { return Ppxs; }
        //}
        [MultilingualCategory("Structure"), MultilingualDisplayName("{0}1", "Edge")]
        public virtual LineSegmentBase Line1
        {
            get { return Lines[0]; }
            set { SetLine(0, value); }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("{0}2", "Edge")]
        public virtual LineSegmentBase Line2
        {
            get { return Lines[1]; }
            set { SetLine(1, value); }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("{0}3", "Edge")]
        public virtual LineSegmentBase Line3
        {
            get { return Lines[2]; }
            set { SetLine(2, value); }
        }
        [MultilingualCategory(null, "Sketchpad", "Display"), MultilingualDisplayName(null, "InCenter", "Displayer")]
        public PropertyDisplayer InCenterDisplayer
        {
            get { return nxDisplayer; }
            set { nxDisplayer = value; }
        }
        [MultilingualCategory(null, "Sketchpad", "Display"), MultilingualDisplayName(null, "CircumCenter", "Displayer")]
        public PropertyDisplayer CircumCenterDisplayer
        {
            get { return wxDisplayer; }
            set { wxDisplayer = value; }
        }
        [MultilingualCategory(null, "Sketchpad", "Display"), MultilingualDisplayName(null, "OrthoCenter", "Displayer")]
        public PropertyDisplayer OrthoCenterDisplayer
        {
            get { return cxDisplayer; }
            set { cxDisplayer = value; }
        }
        public override void RefreshPropertyDisplayersLocation()
        {
            InCenterDisplayer.RefreshLocation();
            CircumCenterDisplayer.RefreshLocation();
            OrthoCenterDisplayer.RefreshLocation();
            base.RefreshPropertyDisplayersLocation();
        }
        public override void RefreshPropertyDisplayersText()
        {
            InCenterDisplayer.RefreshText();
            CircumCenterDisplayer.RefreshText();
            OrthoCenterDisplayer.RefreshText();
            base.RefreshPropertyDisplayersText();
        }
        public override void PaintProperties(Graphics gra)
        {
            if (ObjectState == ObjectState.Normal && Visible)
            {
                InCenterDisplayer.Paint(gra);
                CircumCenterDisplayer.Paint(gra);
                OrthoCenterDisplayer.Paint(gra);
            }
            base.PaintProperties(gra);
        }
        public override PointD AnchorPoint(PropertyDisplayer disp)
        {
            if (disp == InCenterDisplayer)
            {
                return PInCenter;
            }
            else if (disp == CircumCenterDisplayer)
            {
                return PCircumCenter;
            }
            else if (disp == OrthoCenterDisplayer)
            {
                return POrthoCenter;
            }
            return base.AnchorPoint(disp);
        }
        protected void calcCenters(PointD pt1, PointD pt2, PointD pt3)
        {
            InCenter = Utility.GetInCenter(pt1, pt2, pt3);
            CircumCenter = Utility.GetCircumCenter(pt1, pt2, pt3);
            OrthoCenter = Utility.GetOrthoCenter(pt1, pt2, pt3);
            BaryCenter = Utility.GetBaryCenter(new PointD[] { pt1, pt2, pt3 });
            PInCenter = Pad.XYToPxy(InCenter);
            PCircumCenter = Pad.XYToPxy(CircumCenter);
            POrthoCenter = Pad.XYToPxy(OrthoCenter);
            //Pzx在PolygonBase中计算
        }
        public override bool CanDrawVirtual
        {
            get
            {
                switch (OrderIndex)
                {
                    case 0:
                        return Line2 != null;
                    case 1:
                        return Line3 != null;
                    case 2:
                        return Line1 != null;
                }
                return base.CanDrawVirtual;
            }
        }
        public override void PaintVirtualObjects(Graphics gra)
        {
            if (CanDrawVirtual)
            {
                switch (OrderIndex)
                {
                    case 0:
                        gra.FillPolygon(Core.Helper.Painter.VirtualBrush, new PointF[] { Line1.Point1.Pxy.ToPointF(), Line2.Point1.Pxy.ToPointF(), Line2.SpareCoordinate_.ToPointF() });
                        gra.DrawLineSegment(Line2.SpareCoordinate_, Line1.Point1.Pxy);
                        break;
                    case 1:
                        gra.FillPolygon(Core.Helper.Painter.VirtualBrush, new PointF[] { Line1.Point1.Pxy.ToPointF(), Line3.Point1.Pxy.ToPointF(), Line3.SpareCoordinate_.ToPointF() });
                        gra.DrawLineSegment(Line3.SpareCoordinate_, Line1.Point1.Pxy);
                        break;
                    case 2:
                        gra.FillPolygon(Core.Helper.Painter.VirtualBrush, new PointF[] { Line3.Point1.Pxy.ToPointF(), Line1.Point1.Pxy.ToPointF(), Line1.SpareCoordinate_.ToPointF() });
                        gra.DrawLineSegment(Line1.SpareCoordinate_, Line3.Point1.Pxy);
                        break;
                }
            }
        }
        public override void ComponentBuilding(Base component)
        {
            ShowStatus($"{Resources.Translate("Creating")}{Resources.ColonSeparate}{Name}{Resources.LeftParenthesis}{string.Format(Resources.Translate("Of"), Resources.Translate("InCenter"), Resources.Translate("Coordinate"))}{Resources.ColonSeparate}{Pad.ShowPoint(InCenter)}{Resources.CommaSeparate}{string.Format(Resources.Translate("Of"), Resources.Translate("CircumCenter"), Resources.Translate("Coordinate"))}{Resources.ColonSeparate}{Pad.ShowPoint(CircumCenter)}{Resources.CommaSeparate}{string.Format(Resources.Translate("Of"), Resources.Translate("OrthoCenter"), Resources.Translate("Coordinate"))}{Resources.ColonSeparate}{Pad.ShowPoint(OrthoCenter)}");
            base.ComponentBuilding(component);
        }
        public override void ComponentChanged(ShapeBase component)
        {
            calcCenters(InPoints[0].NewXY, InPoints[1].NewXY, InPoints[2].NewXY);
            base.ComponentChanged(component);
        }
        protected override void ClickOrder(IList<PointCreatingArgs> args, int clickTimes, Predicate<PointCreatingArgs> act)
        {
            if (act == null) return;
            switch (OrderIndex)
            {
                case 1:
                    if (!act(args[0])) return;
                    if (!act(args[2])) return;
                    if (!act(args[1])) return;
                    return;
                case 2:
                    if (!act(args[2])) return;
                    if (!act(args[0])) return;
                    if (!act(args[1])) return;
                    return;
            }
            base.ClickOrder(args, clickTimes, act);
        }
        public override PropertyDisplayer[] PropertyDisplayersCheckNearBy(PointD Plocation)
        {
            List<PropertyDisplayer> res = new List<PropertyDisplayer>(base.PropertyDisplayersCheckNearBy(Plocation));
            if (InCenterDisplayer.InRegion(Plocation))
            {
                res.Add(InCenterDisplayer);
            }
            if (CircumCenterDisplayer.InRegion(Plocation))
            {
                res.Add(CircumCenterDisplayer);
            }
            if (OrthoCenterDisplayer.InRegion(Plocation))
            {
                res.Add(OrthoCenterDisplayer);
            }
            return res.ToArray();
        }
    }
}
